// Copyright 2008 Steve Spiller. All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions are met:
// 
//    1. Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//    2. Redistributions in binary form must reproduce the above copyright 
//       notice, this list of conditions and the following disclaimer in the 
//       documentation and/or other materials provided with the distribution.
//       
// THIS SOFTWARE IS PROVIDED BY THE KAOS PROJECT ``AS IS'' AND ANY EXPRESS 
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 
// NO EVENT SHALL THE PROJECT OWNERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "DriverWin.h"
#include "LpcScanner.h"

#include <iostream>
#include <fstream>
#include <sstream>

CDriverWindow::CDriverWindow()
{
    m_textBuffer.push_back(std::string("KaOS Mud Driver"));
    m_textBuffer.push_back(std::string("Version 1.0"));
    m_textBuffer.push_back(std::string(""));

    CLpcScanner scanner(std::string("sample.c"));
    std::ostringstream stream;
    CLpcToken *token = 0;

    scanner.SetOutputStream(stream);

    do
    {
        if(token)
        {
            delete token;
        }
        
        token = scanner.GetToken();
    } 
    while(token->GetToken() != CLpcScanner::EndOfFile);

    std::string sub = stream.str();
    size_t pos = sub.find(10);
    
    while(pos != std::string::npos)
    {
        m_textBuffer.push_back(sub.substr(0, pos));
        sub = sub.substr(pos + 1);
        pos = sub.find(10);
    }

    m_textBuffer.push_back(sub);
}

CDriverWindow::~CDriverWindow()
{
}

// ***************************************************************************
// Function Name: OnCreate
//
// Purpose: Handle WM_CREATE
//
// Description:
//    Called when the window is being created.
LRESULT CDriverWindow::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    return FALSE;
}

// ***************************************************************************
// Function Name: OnEraseBkgnd
//
// Purpose: Handle WM_ERASEBKGND
//
// Description:
//    Called to determine if the window erases it's own background.
//LRESULT CDriverWindow::OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
//{
//    return FALSE;
//}

// ***************************************************************************
// Function Name: OnSize
//
// Purpose: Handle WM_SIZE
//
// Description:
//    Called when the window is resized
LRESULT CDriverWindow::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    TEXTMETRIC  tm;
    SCROLLINFO  si;
    RECT        rc;

    GetTextMetrics(GetDC(), &tm);
    GetClientRect(&rc);

    m_rowHeight = tm.tmHeight + tm.tmExternalLeading;
    m_numRows   = rc.bottom / m_rowHeight;

    si.cbSize = sizeof(si);
    si.fMask  = SIF_PAGE | SIF_RANGE | SIF_DISABLENOSCROLL;
    si.nPage  = m_numRows;
    si.nMin   = 0;
    si.nMax   = m_textBuffer.size() - 1;

    SetScrollInfo(SB_VERT, &si, TRUE);

    RedrawWindow();

    return FALSE;
}

// ***************************************************************************
// Function Name: OnVScroll
//
// Purpose: Handle WM_VSCROLL
//
// Description:
//    Called when vertical scroll bar is moved
LRESULT CDriverWindow::OnVScroll(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    SCROLLINFO si;
    int        pos;

    si.cbSize = sizeof(si);
    si.fMask  = SIF_ALL;

    GetScrollInfo(SB_VERT, &si);

    pos = si.nPos;

    switch(LOWORD(wParam))
    {
        case SB_TOP:        si.nPos = si.nMin; break;
        case SB_BOTTOM:     si.nPos = si.nMax; break;
        case SB_LINEUP:     si.nPos -= 1; break;
        case SB_LINEDOWN:   si.nPos += 1; break;
        case SB_PAGEUP:     si.nPos -= si.nPage; break;
        case SB_PAGEDOWN:   si.nPos += si.nPage; break;
        case SB_THUMBTRACK: si.nPos = si.nTrackPos;
    }

    si.fMask = SIF_POS;

    SetScrollInfo(SB_VERT, &si, TRUE);
    GetScrollInfo(SB_VERT, &si);

    if(si.nPos != pos)
    {
        ScrollWindow(0, m_rowHeight * (pos - si.nPos), NULL, NULL);
        UpdateWindow();
    }

    return FALSE;
}

// ***************************************************************************
// Function Name: OnPaint
//
// Purpose: Handle WM_PAINT
//
// Description:
//    Called when the window needs to be redrawn
LRESULT CDriverWindow::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    PAINTSTRUCT ps;
    HDC         hdc;
    RECT        client;
    UINT        pos;
    
    pos = GetScrollPos(SB_VERT);
    hdc = BeginPaint(&ps);
    
    GetClientRect(&client);

    for(UINT x = pos, i = 0; x < m_textBuffer.size(); x++, i += m_rowHeight)
    {
        RECT rc;

        rc.left   = 0;
        rc.top    = i;
        rc.right  = client.right;
        rc.bottom = i + m_rowHeight;

        DrawText(hdc, m_textBuffer[x].c_str(), -1, &rc, DT_SINGLELINE | DT_WORD_ELLIPSIS);
    }

    EndPaint(&ps);

    return FALSE;
}

// ***************************************************************************
// Function Name: OnQueryEndSession
//
// Purpose: Handle WM_QUERYENDSESSION
//
// Description:
//    Called when the system wants us to shutdown.
LRESULT CDriverWindow::OnQueryEndSession(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    return TRUE;
}

// ***************************************************************************
// Function Name: OnEndSession
//
// Purpose: Handle WM_ENDSESSION
//
// Description:
//    Called when the system wants us to shutdown.
LRESULT CDriverWindow::OnEndSession(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    PostQuitMessage(0);
    return FALSE;
}

// ***************************************************************************
// Function Name: OnDestroy
//
// Purpose: Handle WM_DESTROY
//
// Description:
//    Called when the window is closed.
LRESULT CDriverWindow::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    PostQuitMessage(0);
    return FALSE;
}
